package com.itqf.utils;


import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 1.创建连接池
 * 2.获取连接池中对象
 * 3.获取连接池
 * 4.事务的控制(开启、提交、回滚)
 * 5.关闭资源
 */
public class DbUtils {

    //初始化连接池对象
    private static DruidDataSource ds ;

    //存储一个共享的连接对象(为线程存储了共享的对象)(方便事务控制的统一性)
    private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<>();

    //类加载（创建连接池）
    static {
        //加载配置文件
        Properties prop = new Properties();

        //创建流，读取配置文件的信息
        InputStream in = DbUtils.class.getResourceAsStream("/database.properties");

        //将读取到的信息加载到prop配置文件中
        try {
            prop.load(in);

            //1.创建连接池
            ds = (DruidDataSource)DruidDataSourceFactory.createDataSource(prop);
            System.out.println("创建连接池成功！！！");
        } catch (IOException e) {
            System.out.println("信息加载到配置文件失败！！！");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("创建连接池失败！！！");
            e.printStackTrace();
        }
    }


    //2.获取连接池中对象

    public static Connection getConnection(){

        //保证在事务过程中都是共享一个连接对象
        Connection connection = threadLocal.get();
        if (connection == null) {
            try {
                //通过连接池获取连接对象
                connection = ds.getConnection();

                //将从连接池中获取到的连接对象存入threadLocal中(保证事务的统一性)

                threadLocal.set(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return connection ;
    }

    //3.获取连接池
    //获取连接池
    public static DataSource getDataSource(){
        return ds ;
    }

    //事务控制
    //4.开启事务
    public static void begin(){

        Connection connection = null ;

        try {
            //拿到连接对象
            connection = getConnection();
            System.out.println("开启事务的连接对象:"+connection);

            //将自动提交事务改为手动提交事务（开启事务）
            connection.setAutoCommit(false);
            System.out.println("开启事务成功！！！");
        } catch (SQLException e) {
            System.out.println("开启事务失败！！！");
            e.printStackTrace();
        }
    }

    //5.提交事务
    public static void Commit(){
        Connection connection = null ;

        //提交事务
        try {
            //拿到连接对象
            connection = getConnection() ;
            System.out.println("手动提交事务的连接对象:"+connection);
            connection.commit();
            System.out.println("手动提交事务成功！！！");
        } catch (SQLException e) {
            System.out.println("手动提交事务失败！！！");
            e.printStackTrace();
        }

        //不管是否成功提交事务，都要关闭资源
        finally {
            closeAll(connection,null,null);
        }
    }

    //6.回滚事务
    public static void Rollback(){
        Connection connection = null ;
        try {
            connection = getConnection();
            System.out.println("回滚事务的连接对象:"+connection);
            connection.rollback();
            System.out.println("事务回滚成功！！！");
        } catch (SQLException e) {
            System.out.println("事务回滚失败！！！");
            e.printStackTrace();
        }
        //关闭资源
        finally{
            closeAll(connection,null,null);
        }
    }


    //5.释放资源
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        //非空判断
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (connection != null) {
                connection.close();
                //关闭连接后，移除已关闭的connection对象
                threadLocal.remove();
            }
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            //关闭资源失败！！！
            System.out.println("关闭资源失败！！！");
            e.printStackTrace();
        }
    }
}
